package jmine.tec.web.servlet.session;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;

import jmine.tec.utils.io.NullOutputStream;

/**
 * {@link HttpSessionActivationListener} que 'limpa' a {@link HttpSession}, removendo os atributos nao serializaveis
 * 
 * @author takeshi
 */
public class SessionCleanerActivationListener implements HttpSessionActivationListener {

    /**
     * {@inheritDoc}
     */
    public void sessionWillPassivate(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        Enumeration attributeNames = session.getAttributeNames();
        List<String> toRemove = new LinkedList<String>();
        while (attributeNames.hasMoreElements()) {
            String name = String.valueOf(attributeNames.nextElement());
            if (!isSerializable(session.getAttribute(name))) {
                toRemove.add(name);
            }
        }
        for (String name : toRemove) {
            session.removeAttribute(name);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void sessionDidActivate(HttpSessionEvent se) {
    }

    /**
     * Verifica se um objeto eh serializavel, tentando de fato serializar em uma stream vazia
     * 
     * @param instance {@link Object}
     * @return boolean
     */
    public static boolean isSerializable(Object instance) {
        try {
            ObjectOutputStream oout = new ObjectOutputStream(NullOutputStream.getInstance());
            oout.writeObject(instance);
            oout.flush();
            return true;
        } catch (IOException e) {
            return false;
        }
    }

}
